iT邦幫忙

2024 iThome 鐵人賽

DAY 8
0
Modern Web

Dive into CSS Challenge:從問題到解決方案的實踐之旅系列 第 8

Day 8 - CSS Challenge #6:Profile卡片介面(上)

  • 分享至 

  • xImage
  •  

題目

CSS Challenge Day6
https://ithelp.ithome.com.tw/upload/images/20240919/20169403m3oO3a0wtR.png

上面的圖是題目,而我們要做出幾乎一樣的樣子,題目中還有附上出題官方的CodePen,也有附上給我們解題用的template,當我們真的不會的時候,還是可以參考他們的寫法,所以沒有想像中困難。

我做好的此題CSS Challeage解答

那麼我們就開始吧。

題目分析

這個題目要求我們製作一個Profile的介面。
介面卡片底下是一個漸層的陰影,介面卡片上面的每個按鈕包含右邊的Posts, Likes, Follower都有滑鼠指上的效果。

主要挑戰的是圓形的照片區塊,滑鼠指上線條圖節點的時候,外圍的線條要有360度的交叉旋轉,外圈的向右順時針旋轉,內圈的向左逆時針旋轉。
且兩個圓圈之間的視覺上要看起來距離是平均的,必須是兩個有缺口的同心圓。

開始解題

基礎架構

<div class="frame">
	<div class="card">
		<!-- left side -->
		<div class="profile">
            <div class="profilePic"></div>
            <div class="info"></div>
            <div class="action"></div>
        </div>
		<!-- right side -->
		<div class="statistic"></div>
	</div>
</div>

一開始先開出基礎的版型,我們使用官方提供的template做修改,把 .center 改成 .card 做為卡片區塊,在裡面再區分成左右兩邊,左邊是 .profile,右邊是.statistic


底色

$coffee: #786450;

.frame {
    background: linear-gradient(45deg,  #eebe6b 0%,#ca7c4d 100%);
    color: $coffee;
}

這時候就可以使用我們第一天教的小工具來吸色,再使用工具內的漸層產生工具(可以參考第一天的文章),來製作底色(當然要自己也也可以,這邊我使用45度來寫漸層。

另外,由於卡片整體的顏色都是咖啡色,加上照片四周的動畫區塊,下面圓角按鈕在滑鼠指上後變化的底色,看起來也都是同一個顏色,所以這邊我直接使用變數儲存這個顏色。


卡片結構

.card {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
  width: 320px;
  height: 300px;
  border-radius: 3px;
  box-shadow: 10px 10px 15px 0 rgba(0,0,0,.3);
  background-color: #fff;
  display: flex;
}

先幫中間的卡片區塊做出樣式。
置中的部分,本來template在 .center 就已經做好了,所以我們只需要加上寬高、些微的圓角、背景色跟看起來類似的 box-shadow

由於我們已經確定 .card 內部的樣子是需要左右擺放的,所以這裡我們直接在卡片上加上一句 display: flex 讓裡面左右兩個 div 可以實現併排(雖然畫面上衣片空白都還看不到)
做好之後長這樣:
https://ithelp.ithome.com.tw/upload/images/20240919/20169403FSmbKrx3d5.png

左邊 Profile 區塊

<!-- left side -->
<div class="profile">
    <div class="profilePic"></div>
    <div class="info">
        <h1 class="name">Hitomi Yang</h1>
		<span class="job">Front-end Developer</span>
    </div>
    <div class="action">
        <button class="btn" type="button">Follow</button>
        <button class="btn" type="button">Message</button>
    </div>
</div>

接著設定卡片內左右物件內的元件,.profile 內依序是.profile info action,我習慣先把東西都整理好再來設定CSS。

.info 內我就放上我自己的名稱跟職稱,分別用 h1span 來包裹他們。

.action 內就照著題目放入兩個 button,取名為 .btn,文字則依照題目的貼上不同的文字內容。

右邊 Statistic 區塊

<div class="statistic">
	<div class="box">
		<span class="value">523</span>
		<span class="param">Posts</span>
	</div>
	<div class="box">
		<span class="value">1387</span>
		<span class="param">Likes</span>
	</div>
	<div class="box">
		<span class="value">146</span>
		<span class="param">Follower</span>
	</div>
</div>

右邊是由三個資訊塊組成的,所以我先設定右邊內的每個區塊都叫 .box,這樣他們能才吃到一樣的樣式。
.box 裡面再依照內容,用兩個 sapn 去包裹數值 .value 跟名稱 .param,照著題目把內容的文字都貼上去,接著就來設定它的樣式。

剛畫好還沒有任何 style 的時候長這樣:
https://ithelp.ithome.com.tw/upload/images/20240919/201694038h3Slv8zfm.png


卡片style設定

左邊 Profile 的 style

.profile {
	width: 220px;
	background-color: #fff;
    display: flex;
	justify-content: center;
	align-items: center;
    flex-direction: column;
    
	& > * + * {
		margin-top: 20px;
	}
}

先設定好左邊 .profile 區域的寬度,將他的 display 設定為 flex,並設定 flex-direction: column,讓排列的順序由上往下排。

接著加入 justify-content: centeralign-items: center,這是為了要排列內部的所有東西除了垂直置中以外,也能在這個區塊的上下置中的位置呈現。

這裡我喜歡的一個小技巧是 & > * + * 選擇器,他能選擇這個區塊內所有第一層的物件中,他的後面還有物件的物件。這樣講可能拗口,簡單說,他就是能讓你選擇「這個區塊內,第一層的所有物件,除了第一個物件」,選到他們之後,我就會加上 margin-top: 20px 讓他們彼此之間有 20px 的固定間距。
但是第一個物件,他距離上面是不會有 margin 的,這真的很方便。

大區塊調整完了,來製作內容,照片那區由於要做動畫,我們最後再來弄。
我們首先調整名字跟職稱的部分。

.info {
	.name {
		padding: 0;
		margin: 0;
		line-height: 1;
		font-size: 15px;
		font-weight: 600;
		text-align: center;
	}
	.job {
		font-size: 11px;
		font-weight: 300;
	}
}

name 這邊因為我使用了 h1,所以要進行 CSS Reset,我就在裡面針對 margin padding 加入了0的設定。調整字體大小等等,跟題目類似就可以了。
剛做好的時候長這樣:
https://ithelp.ithome.com.tw/upload/images/20240919/201694039JsU9CIlSK.png

我們繼續把底下按鈕的部分做完。

.action {
	display: flex;
	flex-direction: column;
	width: 120px;
			
	& > * + * {
		margin-top: 10px;
	}
}

首先是調整他的排列,跟剛剛 .profile 的部分一樣,我們先使用 flex 屬性讓他從上往下排列,設定區塊的寬度,然後用剛剛教的間距小技巧,讓兩個上下按鈕之間有一定的距離。
https://ithelp.ithome.com.tw/upload/images/20240919/20169403VPhKYykubS.png

這還沒完,接著就來調整按鈕的樣子,還有滑鼠指上的動態。

.action {
    ...
	.btn {
		border: 1px solid $coffee;
		background-color: #fff;
		border-radius: 24px;
		color: $coffee;
		font-size: 12px;
		font-weight: 600;
		padding: 7px 12px;
		width: 100%;
		cursor: pointer;
		transition: all ease-in-out .4s;
		&:hover {
			background-color: $coffee;
			color: #fff;
		}
	}
}

依照題目的樣式,先加入邊框跟底色,調整一下字體的大小,修改 border 的圓角,加入 :hover 時的樣式,滑鼠指上時,我們只有改變背景色跟字體顏色。

最後不要忘記加入動態漸變的關鍵屬性 transition: all ease-in-out .4s在按鈕本人身上。選擇 all 是為了讓他所有屬性都能使用,包含背景跟字體顏色,.4s 的漸變時間設定好之後,加上 cursor: pointer ,按鈕的區域就全部都完成了。
https://ithelp.ithome.com.tw/upload/images/20240919/20169403yNZCTAsU4c.png

右邊 Statistic 的 style

.statistic {
	display: grid;
	grid-template-rows: repeat(3, minmax(0, 1fr));
	grid-gap: 1px 0;
}

右邊的區塊是用3個格子組成的,加上格子之間都要有白色的空隙,這段如果用 border 來寫,個人覺得很醜,所以這邊又是我最愛的 grid 的主場了。

設定它有3個一樣的 row,並且設定它們之間上下有 1pxgap,就這樣漂亮的完成了基礎的架構。
https://ithelp.ithome.com.tw/upload/images/20240919/20169403Wy2IPbp3N1.png

再來做裡面每個 .box 的樣式跟文字,加上 :hover 的樣式。

.statistic {
    ...
    .box {
        width: 100%;
        display: flex;
		flex-direction: column;
		text-align: center;
		background-color: #F5E8DF;
		justify-content: center;
		cursor: pointer;
		transition: all ease-in-out .5s;
		&:hover {
			background-color: #E1CFC2;
		}
		.value {
			font-size: 17px;
			font-weight: 600;
		}
		.param {
			font-size: 11px;
		}
	}
}

每個 .box 設定成 flex ,並且使用 flex-direction: column 讓它的方向是從上往下,這樣裡面的文字就可以漂亮的上下並排。
再來就是基礎的 flex 設定,讓物建在裡面能漂亮的上下左右置中。

底色一樣使用第一天的小工具來吸色,設定它 :hover 時的底色之後,不要忘了回到 .box 本人身上加上 transition: all ease-in-out .5s 這邊我設定 .5s,看起來一切都非常完美,畫面卻有個問題:
https://ithelp.ithome.com.tw/upload/images/20240919/20169403G9I8Keg0Im.png

明明寬度已經設定100%了,為什麼不會滿版呢?

其實這時候如果你把卡片寬度剪去左邊 .profile 的寬度,把剩下的寬度設定在 .statistic 身上就可以解決,但我偏偏不要!我就是想要他自由擴展。

還記得我們在卡片 .card 上面設定了 flex 這個屬性來把卡片分左右兩邊嗎?
這時候就是 flex 在搞事。
flex 預設不會自動填滿剩餘的空間,尤其是我們父元素內有其他子元素(例如 .profile )限制了空間的使用時。

這時候有兩種解法:
解法一
1. 在你要限制寬度的那個區塊上(這裡的話是 .profile),加上 flex:none 不允許他伸展或收縮以適應父容器的變化。
2. 在你要根據剩餘空間自動調整寬度的區塊上(這裡的話是 .statistic),加上 flex:auto,讓他根據剩餘空間自動調整寬度,同時允許他隨著父容器變化而擴展。

解法二:在要自由擴展的那個區塊(這裡的話是 .statistic),加上 flex-grow: 1,一樣是為了設定讓他可以自由擴展。

這樣我們的基礎版面就做好了:

https://ithelp.ithome.com.tw/upload/images/20240919/201694037g8bgRExZd.png

由於篇幅太長了,我決定分兩篇寫,下一篇再來寫後面的個人頭像跟動畫的部分,敬請期待。


Wrap up and go home

希望改變了這種按照步驟的寫法,能讓更多人看得懂,也能跟我一樣喜歡上寫CSS。

那今天就先到這裡,明天我們再繼續來玩下集。


上一篇
Day 7 - CSS Challenge #5:Weekly Report 介面(下)
下一篇
Day 9 - CSS Challenge #6:Profile卡片介面(下)
系列文
Dive into CSS Challenge:從問題到解決方案的實踐之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言